/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * $Id$ CatalogService.java
 * Universidad de los Andes (Bogotá - Colombia)
 * Departamento de Ingeniería de Sistemas y Computación
 * Licenciado bajo el esquema Academic Free License version 2.1
 *
 * Ejercicio: Muebles los Alpes
 * Autor: Camilo Alvarez
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
package com.losalpes.catalogo.servicios;

import com.losalpes.catalogo.entities.Mueble;
import com.losalpes.catalogo.entities.Promocion;
import com.losalpes.catalogo.excepciones.InvalidDataException;
import com.losalpes.catalogo.excepciones.InvalidOperationException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.Topic;

/**
 * Implementacion de los servicios del catalogo que se le prestan al sistema. [Mock Object]
 * @author Camilo Alvarez
 */
@Stateful
public class CatalogService implements ICatalogServiceLocal,ICatalogServiceRemote {

    // --------------------------------------------
    // Atributos
    // --------------------------------------------

    /**
     * Mueble que està siendo editado por la aplicación
     */
    private Mueble cMueble;

    /**
     * Promocion que està siendo editada por la aplicación
     */
    private Promocion promocion;

    /**
     * Unidad de persistencia de la aplicacion
     */
    @EJB
    private IPersistenceServices persistenceServices;

    // --------------------------------------------
    // Recursos JMS
    // --------------------------------------------

    /**
     * ConnectionFactory
     */
    @Resource(mappedName="jms/promocionesTopicFactory")
    private ConnectionFactory connectionFactory;
    /**
     * Topic
     */
    @Resource(mappedName="jms/promocionesTopic")
    private Topic topic;

    // --------------------------------------------
    // Constructor
    // --------------------------------------------

    /**
     * Crea una nueva instancia de Vendedor y la retorna.
     * @return vendedor. Nueva instancia de vendedor.
     */
    public Mueble newMueble() {
        
        cMueble = new Mueble();
        return cMueble;
    }

    /**
     * Modifica un vendedor dentro de la persistencia del sistema.
     * @return vendedor. Objeto modificado de la instancia de vendedor que se modifico.
     */
    public Mueble createOrUpdate()throws InvalidDataException{
        if(cMueble.getAlto()<=0){
            throw new InvalidDataException("La altura debe ser un nÃºmero positivo");
        }
        if(cMueble.getAncho()<=0){
            throw new InvalidDataException("El ancho debe ser un nÃºmero positivo");
        }
        if(cMueble.getCantidad()<0){
            throw new InvalidDataException("La cantidad debe ser un nÃºmero positivo o cero");
        }
        if(cMueble.getProfundidad()<=0){
            throw new InvalidDataException("La profundidad debe ser un nÃºmero positivo");
        }
        if(cMueble.getPrecio()<0){
            throw new InvalidDataException("El precio debe ser un nÃºmero positivo");
        }
        if(cMueble.getPeso()<0){
            throw new InvalidDataException("El peso debe ser un nÃºmero positivo");
        }
        if(cMueble.getNombre()==null||cMueble.getNombre().isEmpty()){
            throw new InvalidDataException("Debe ingresar un nombre no vacÃ­o");
        }
        if (cMueble.getReferencia() == null || cMueble.getReferencia().isEmpty()) {
            try {
                persistenceServices.create(cMueble);
            } catch (InvalidOperationException ex) {
            }
        } else {
            persistenceServices.update(cMueble);
        }
        return cMueble;
    }

	/**
     * Retorna la lista de todos los vendedores registrados en el sistema.
     * @return list. Lista de todos los vendedores registrados en el sistema.
     */
    public List<Mueble> findAll() {
        return persistenceServices.findAll(Mueble.class);
    }

    /**
     * Retorna un vendedor dada su identificación.
     * @param id. Identificador único del vendedor.
     * @return vendedor. Vendedor cuyo identificador corresponde con el parametro.
     */
    public Mueble findByIdentificacion(String id) {
        return (Mueble)persistenceServices.findById(Mueble.class,id);
    }

    /**
     * Permite eliminar un vendedor de la persistencia del sistema.
     */
    @Remove
    public void delete() {
        try {
            persistenceServices.delete(cMueble);
        } catch (InvalidOperationException ex) {
            Logger.getLogger(CatalogService.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Retorna el vendedor actual.
     * @return vendedor. Vendedor actual.
     */
    public Mueble getMueble() {
        return cMueble;
    }

    /**
     * Permite asignar el vendedor actual.
     * @param id. Identificador de nuevo cendedor actual.
     * @return vendedor. Nuevo vendedor actual.
     */
    public void setMueble(Mueble mueble) {
        cMueble=mueble;
    }

    public void addPromocion(Mueble mueble, Promocion promocion) {
        try {
            this.cMueble = mueble;
            this.promocion = promocion;
            notificarPromocion();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Message createPromocionMessage(Session session) throws JMSException {
        MapMessage mapMessage = session.createMapMessage();
        mapMessage.setString("mueble_referencia", cMueble.getReferencia());
        mapMessage.setString("mueble_nombre", cMueble.getNombre());
        mapMessage.setInt("mueble_cantidad", cMueble.getCantidad());
        mapMessage.setInt("mueble_precio", cMueble.getPrecio());
        mapMessage.setString("promocion_referencia", promocion.getReferencia());
        mapMessage.setLong("promocion_fecha_inicial", promocion.getFechaInicial().getTime());
        mapMessage.setLong("promocion_fecha_final", promocion.getFechaFinal().getTime());
        mapMessage.setString("promocion_texto", promocion.getTexto());
        return mapMessage;
    }

    private void notificarPromocion() throws JMSException {
        Connection connection = null;
        Session session = null;
        try {
            connection = connectionFactory.createConnection();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer messageProducer = session.createProducer((Destination) topic);
            messageProducer.send(createPromocionMessage(session));
        }
        catch (Exception e) {
            e.printStackTrace();
            throw new JMSException("CatalogService:notificarPromocion:" + e.getMessage());
        }
        finally {
            if (session != null) {
                try {
                    session.close();
                }
                catch (JMSException jme) {
                    jme.printStackTrace();
                }
                if (connection != null) {
                    connection.close();
                }
            }
        }
    }

    /**
     * @return the promocion
     */
    public Promocion getPromocion() {
        return promocion;
    }

    /**
     * @param promocion the promocion to set
     */
    public void setPromocion(Promocion promocion) {
        this.promocion = promocion;
    }
}